package org.hackystat.sdsa.analyzer.control.processor;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.logging.Logger;

import javax.xml.datatype.XMLGregorianCalendar;

import org.hackystat.sdsa.analyzer.model.activity.Activity;
import org.hackystat.sdsa.analyzer.model.activity.UnitTestActivity;
import org.hackystat.sdsa.analyzer.model.activity.edit.EditActivity;
import org.hackystat.sdsa.analyzer.model.activity.edit.ProductionEditActivity;
import org.hackystat.sensorbase.resource.sensordata.jaxb.Properties;
import org.hackystat.sensorbase.resource.sensordata.jaxb.Property;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;
import org.hackystat.utilities.tstamp.Tstamp;
import org.junit.Before;
import org.junit.Test;

/**
 * Test the activity builder.
 * 
 * @author hongbing
 *
 */
public class TestActivityBuilder {
  /** Define an ActivityBuilder. */  
  private ActivityBuilder builder;
  private Logger logger;
  
  /**
   * Prepare test environment.
   */
  @Before public void setUp() {
    this.logger = Logger.getLogger(TestActivityBuilder.class.getName());
    this.builder = new ActivityBuilder(this.logger);
  }
  
  /**
   * Makes a document edit activity.
   * 
   * @return Sensor data of the document edit.
   * @throws Exception If any error occurs.
   */
  private SensorData makeDocumentEdit() throws Exception {
    /** Document edit data. */
    SensorData docEditData = new SensorData();
    XMLGregorianCalendar tstamp = Tstamp.makeTimestamp("2007-11-17T10:25:16.949-08:00");
    docEditData.setTimestamp(tstamp);
    docEditData.setResource("file:/C:/cvs/work/com/foo/jboss-config.xml");
    docEditData.setSensorDataType("DevEvent");
    
    Properties props = new Properties();
    Property type = new Property();
    type.setKey("Type");
    type.setValue("Edit");
    props.getProperty().add(type);
    
    Property subType = new Property();
    subType.setKey("Subtype");
    subType.setValue("StateChange");
    props.getProperty().add(subType);
    
    Property currentSize = new Property();
    currentSize.setKey(EditActivity.CURRENT_SIZE);
    currentSize.setValue("300");
    props.getProperty().add(currentSize);
    
    docEditData.setProperties(props);
    
    return docEditData;
  }
  
  /**
   * Make a production edit sensor data.
   * 
   * @return Sensor data.
   * @throws Exception If any error occurrs.
   */
  private SensorData makeProductionEditData() throws Exception {
    /** Production code edit data. */
    SensorData productEditData = new SensorData();
    XMLGregorianCalendar tstamp = Tstamp.makeTimestamp("2007-11-17T10:25:16.949-08:00");
    productEditData.setTimestamp(tstamp);
    productEditData.setResource("file:/C:/cvs/work/com/foo/Bar.java");
    productEditData.setSensorDataType("DevEvent");

    Properties props = new Properties();
    productEditData.setProperties(props);
    
    Property type = new Property();
    type.setKey("Type");
    type.setValue("Edit");
    props.getProperty().add(type);
    
    Property subType = new Property();
    subType.setKey("Subtype");
    subType.setValue("StateChange");
    props.getProperty().add(subType);
    
    Property currentSize = new Property();
    currentSize.setKey(EditActivity.CURRENT_SIZE);
    currentSize.setValue("1560");
    props.getProperty().add(currentSize);

    Property className = new Property();
    className.setKey(ProductionEditActivity.CLASS_NAME);
    className.setValue("com.foo.Bar");
    props.getProperty().add(className);

    Property currentStatements = new Property();
    currentStatements.setKey(ProductionEditActivity.CURRENT_STATEMENTS);
    currentStatements.setValue("36");
    props.getProperty().add(currentStatements);

    Property currentMethods = new Property();
    currentMethods.setKey(ProductionEditActivity.CURRENT_METHODS);
    currentMethods.setValue("2");
    props.getProperty().add(currentMethods);
    
    return productEditData;
  }
  
  /**
   * Makes sensor data.
   * 
   * @return Unit test sensor data.
   * @throws Exception If error occurs.
   */
  private SensorData makeUnitTestData() throws Exception {
    /** UnitTest data. */
    SensorData unitTestData = new SensorData();
    XMLGregorianCalendar tstamp = Tstamp.makeTimestamp("2007-11-17T10:25:16.949-08:00");
    unitTestData.setTimestamp(tstamp);
    unitTestData.setResource("file:/C:/cvs/work/com/foo/TestBar.java");
    unitTestData.setSensorDataType("DevEvent");

    XMLGregorianCalendar runtimeCal = Tstamp.makeTimestamp("2007-11-17T10:25:00.000-08:00");
    unitTestData.setRuntime(runtimeCal);
    
    // Add property
    Properties props = new Properties();
    unitTestData.setProperties(props);

    Property type = new Property();
    type.setKey("Type");
    type.setValue("Test");
    props.getProperty().add(type);
    
    Property failureString = new Property();
    failureString.setKey(UnitTestActivity.FAILURE_STRING);
    failureString.setValue("");
    props.getProperty().add(failureString);

    Property elapsedTime = new Property();
    elapsedTime.setKey(UnitTestActivity.ELAPSED_TIME);
    elapsedTime.setValue("12");
    props.getProperty().add(elapsedTime);


    Property testName = new Property();
    testName.setKey(UnitTestActivity.TEST_NAME);
    testName.setValue("testSingle()");
    props.getProperty().add(testName);

    Property testCase = new Property();
    testCase.setKey(UnitTestActivity.TEST_CASE);
    testCase.setValue("TestBar");
    props.getProperty().add(testCase);

    Property testCount = new Property();
    testCount.setKey(UnitTestActivity.TEST_COUNT);
    testCount.setValue("1");
    props.getProperty().add(testCount);

    Property testIndice = new Property();
    testIndice.setKey(UnitTestActivity.TEST_INDICE);
    testIndice.setValue("1");
    props.getProperty().add(testIndice);

    return unitTestData;
  }
  
  /**
   * Test activity builder. 
   * 
   * @throws Exception If error happens.
   */
  @Test public void testActivityBuilder() throws Exception {
     SensorData docEditData = makeDocumentEdit();
     this.builder.process(docEditData);
     
     List<Activity> activityList = this.builder.getActivityList(); 
     
     assertNotNull("Check the builder", activityList);
     assertEquals("Test size of the activity list #1", 1, activityList.size());

     SensorData productEditData = makeProductionEditData();
     this.builder.process(productEditData);
     assertEquals("Test size of the activity list #2", 2, activityList.size());
     assertTrue("Test activity instance", 
         activityList.get(1) instanceof ProductionEditActivity);
     
     SensorData unitTestData = makeUnitTestData();
     this.builder.process(unitTestData);
     assertEquals("Test size of the activity list #3", 3, activityList.size());
     assertTrue("Test unit test activity instance", 
         activityList.get(2) instanceof UnitTestActivity);
  }
}